import { B3dmBuildOptions, B3dmHeader } from './types';

/**
 * 构建B3DM二进制数据
 * @param options 构建选项（包含GLB和元数据）
 * @returns B3DM的ArrayBuffer
 */
export function buildB3dm(options: B3dmBuildOptions): ArrayBuffer {
  const {
    glbData,
    featureTableJSON = {},
    featureTableBinary = new Uint8Array(0),
    batchTableJSON = {},
    batchTableBinary = new Uint8Array(0),
  } = options;

  // 1. 计算各部分长度
  const featureTableJSONStr = JSON.stringify(featureTableJSON);
  const featureTableJSONByteLength = new TextEncoder().encode(featureTableJSONStr).length;
  const featureTableBinaryByteLength = featureTableBinary.byteLength;
  const batchTableJSONStr = Object.keys(batchTableJSON).length > 0 ? JSON.stringify(batchTableJSON) : '';
  const batchTableJSONByteLength = new TextEncoder().encode(batchTableJSONStr).length;
  const batchTableBinaryByteLength = batchTableBinary.byteLength;
  const glbByteLength = glbData.byteLength;

  // 2. 计算文件总长度（头28字节 + 各部分长度）
  const totalByteLength = 28 + featureTableJSONByteLength + featureTableBinaryByteLength + batchTableJSONByteLength + batchTableBinaryByteLength + glbByteLength;

  // 3. 构建文件头
  const header: B3dmHeader = {
    magic: 'b3dm',
    version: 1,
    byteLength: totalByteLength,
    featureTableJSONByteLength,
    featureTableBinaryByteLength,
    batchTableJSONByteLength,
    batchTableBinaryByteLength,
  };

  // 4. 写入二进制数据
  const arrayBuffer = new ArrayBuffer(totalByteLength);
  const dataView = new DataView(arrayBuffer);
  let offset = 0;

  // 写入文件头（28字节）
  for (const char of header.magic) {
    dataView.setUint8(offset++, char.charCodeAt(0));
  }
  dataView.setUint32(offset, header.version, true); offset += 4;
  dataView.setUint32(offset, header.byteLength, true); offset += 4;
  dataView.setUint32(offset, header.featureTableJSONByteLength, true); offset += 4;
  dataView.setUint32(offset, header.featureTableBinaryByteLength, true); offset += 4;
  dataView.setUint32(offset, header.batchTableJSONByteLength, true); offset += 4;
  dataView.setUint32(offset, header.batchTableBinaryByteLength, true); offset += 4;

  // 写入特征表
  new Uint8Array(arrayBuffer).set(new TextEncoder().encode(featureTableJSONStr), offset);
  offset += featureTableJSONByteLength;
  if (featureTableBinaryByteLength > 0) {
    new Uint8Array(arrayBuffer).set(featureTableBinary, offset);
    offset += featureTableBinaryByteLength;
  }

  // 写入批量表
  if (batchTableJSONByteLength > 0) {
    new Uint8Array(arrayBuffer).set(new TextEncoder().encode(batchTableJSONStr), offset);
    offset += batchTableJSONByteLength;
  }
  if (batchTableBinaryByteLength > 0) {
    new Uint8Array(arrayBuffer).set(batchTableBinary, offset);
    offset += batchTableBinaryByteLength;
  }

  // 写入GLB数据
  new Uint8Array(arrayBuffer).set(glbData, offset);

  return arrayBuffer;
}